//
// Created by 12967 on 2022/2/23.
//

#ifndef DATASTRUCTURE_TIERTREE_H
#define DATASTRUCTURE_TIERTREE_H
#include <iostream>
#include "fileNode.h"
#include <vector>
#include <queue>
using namespace std;


struct trieNode
{
    char val=' ';
    bool endPoint=false;
    trieNode **child=NULL;
    FileListNode* files=NULL;
};

class trieTree {
private:
    trieNode* index[26]={};
public:
    trieTree(){
        for(int i=0;i<26;i++){
            index[i]=new trieNode;
            index[i]->val=(char)(i+97);
        }
    };

    void insert(const string & wrd,const string& fName){
        int current=0;
        int length=wrd.size();
        trieNode* p=index[(int)wrd[current]-97];
        while(++current<length){
            char now=wrd[current];
            if(p->child==NULL){
                p->child=new trieNode*[26];
                for(int k=0;k<26;k++){
                    p->child[k]=new trieNode();
                    p->child[k]->val=(char)(k+97);
                }
            }
            p=p->child[(int)now-97];
        }
        p->endPoint=true;
        FileListNode* fileIterator=p->files;
        FileListNode* par;
        while(fileIterator!=NULL){
            if(fileIterator->file==fName){
                return;
            }else{
                par=fileIterator;
                fileIterator=fileIterator->nextFile;
            }
        }if(p->files==NULL){
            p->files=new FileListNode;
            p->files->file=fName;
        }else{
            fileIterator=new FileListNode;
            fileIterator->file=fName;
            par->nextFile=fileIterator;
        }
    };

    void search(const string& targetWord,vector<string>& files,int* biop){
        for(int i=0;i<files.size();i++){
            biop[i]=0;
        }
        int current=0;
        int length=targetWord.size();
        trieNode* p=index[(int)(targetWord[
                current]-97)];
        while(++current<length){
            char now=targetWord[current];
            if(p->child[now-97]->val==' ')
                p->child[now-97]->val=now;
            p=p->child[now-97];
        }
        if(p->endPoint){
            FileListNode* fileIterator=p->files;
            while(fileIterator){
                auto iter=find(files.begin(),files.end(),fileIterator->file);
                auto index2=std::distance(files.begin(),iter);
                biop[index2]=1;
                fileIterator=fileIterator->nextFile;
            }
            cout<<endl;
            return;
        }else{
            cout<<"NO MATCHED FILES!"<<endl;
            return;
        }
    };

    void mutiSearch(vector<string> files){
        auto* command=new queue<string>;
        string s;
        while(cin>>s){
            if(s==",")
                break;
            command->push(s);
        }
        cout<<"WAIT A SEC......"<<endl;
        clock_t start,end;
        start=clock();
        int* result=new int[files.size()];
        this->search(command->front(),files,result);
        command->pop();
        while(!command->empty()){
            bool isOr=true;
            string op=command->front();
            if(op=="AND")
                isOr=false;
            command->pop();
            if(command->empty())
            {
                cout<<"SYNTAX ERROR!!!"<<endl;
                return;
            }else{
                int* result2=new int[files.size()];
                this->search(command->front(),files,result2);
                command->pop();
                if(isOr){
                    for(int i=0;i<files.size();i++){
                        result[i]=result[i]|result2[i];
                    }
                }else{
                    for(int i=0;i<files.size();i++){
                        result[i]=result[i]&result2[i];
                    }
                }

            }
        }
        bool noselected=true;
        cout<<"THE FINAL RESULT IS: "<<endl;
        for(int i=0;i<files.size();i++){
            if(result[i]){
                noselected=false;
                cout<<files[i]<<"\n";
            }

        }
        if(noselected)
            cout<<"NO MATCHED FILES!!!";
        cout<<endl;

        end=clock();
        auto time=(double)(end-start)/CLOCKS_PER_SEC*1000;
        cout<<"Total time:"<<time<<"ms"<<endl;
    }


};


#endif //DATASTRUCTURE_TIERTREE_H
